#include "Player.h"

#include "Projectile.h"

#include "glut.h"
#include "Input.h"
#include "Spawner.h"

#include <algorithm>
#include <iostream>


Player::Player(int playerIndex, int x, int y):
	Movable(x, y, false, Type_Player),
	playerIndex(playerIndex),
	lastHVelocity(0),
	lastVVelocity(0),
	projectilesAllowed(1),
	ignoreInput(false)
{
}


Player::~Player()
{
	std::cout << getName() << " has died!" << std::endl;

	for (std::vector<Projectile*>::iterator it = ownedProjectiles.begin(); it != ownedProjectiles.end(); ++it)
	{
		(*it)->clearOwner();
	}
}


void Player::getTimedDesiredMove(int& hDirection, int& vDirection)
{
	if (ignoreInput)
	{
		return;
	}

	int x = 0;
	int y = 0;
	getLocation(x, y);

	const Input* input = Input::getInstance();
	if (playerIndex == 1)
	{
		if (input->keyPressed('a')) hDirection = -1;
		if (input->keyPressed('d')) hDirection = 1;
		if (input->keyPressed('w')) vDirection = -1;
		if (input->keyPressed('s')) vDirection = 1;
		if (input->keyPressed(' ') && (lastHVelocity != 0 || lastVVelocity != 0))
		{
			spawnProjectile(Spawner::ID_Projectile, x + lastHVelocity, y + lastVVelocity, lastHVelocity, lastVVelocity);
		}
	}
	else if (playerIndex == 2)
	{
		if (input->specialKeyPressed(GLUT_KEY_LEFT )) hDirection = -1;
		if (input->specialKeyPressed(GLUT_KEY_RIGHT)) hDirection = 1;
		if (input->specialKeyPressed(GLUT_KEY_UP   )) vDirection = -1;
		if (input->specialKeyPressed(GLUT_KEY_DOWN )) vDirection = 1;
		if (input->keyPressed('/') && (lastHVelocity != 0 || lastVVelocity != 0))
		{
			spawnProjectile(Spawner::ID_Projectile, x + lastHVelocity, y + lastVVelocity, lastHVelocity, lastVVelocity);
		}
	}

	// Store the last direction for shooting.
	if (hDirection != 0 || vDirection != 0)
	{
		lastHVelocity = hDirection;
		lastVVelocity = vDirection;
	}
}


void Player::handleCollision(GameObject* gameObject)
{
	
}


bool Player::isPassable(const GameObject* gameObject) const
{
	return gameObject->getType() == Type_Monster;
}


void Player::setDrawColor() const
{
	if (playerIndex == 1)
	{
		setColor(0.0f, 0.0f, 1.0f);
	}
	else
	{
		setColor(0.0f, 0.7f, 0.0f);
	}
}


void Player::drawObject(int row, int col) const
{
	// Draw player.
	drawSquare(row, col);
	
	std::vector<drawPoint> points;
	setColor(1,1,1);
	
	glLineWidth(2);

	// Draw eyebrows.
	points.push_back(drawPoint(col + 0.1 , row + 0.4, 0));
	points.push_back(drawPoint(col + 0.25, row + 0.2, 0));
	points.push_back(drawPoint(col + 0.4 , row + 0.4, 0));

	drawInMode(GL_LINE_STRIP, points);

	points.clear();

	points.push_back(drawPoint(col + 0.6 , row + 0.4, 0));
	points.push_back(drawPoint(col + 0.75, row + 0.2, 0));
	points.push_back(drawPoint(col + 0.9 , row + 0.4, 0));

	drawInMode(GL_LINE_STRIP, points);

	points.clear();

	// Draw mouth.
	points.push_back(drawPoint(col + 0.3, row + 0.75, 0));
	points.push_back(drawPoint(col + 0.7, row + 0.75, 0));

	drawInMode(GL_LINES, points);

	glLineWidth(1);

	points.clear();

	// Draw held item.
	if (hasInInventory(InventoryItem_Key) || hasInInventory(InventoryItem_GateKey))
	{
		// Draw normal key in offhand if both are present.
		if (hasInInventory(InventoryItem_Key) && hasInInventory(InventoryItem_GateKey))
		{
			setColor(0.0f, 1.0f, 1.0f);

			points.push_back(drawPoint(col + 0.9, row + 0.7, 0));
			points.push_back(drawPoint(col + 1.1, row + 0.7, 0));
			points.push_back(drawPoint(col + 1.1, row + 0.9, 0));
			points.push_back(drawPoint(col + 0.9, row + 0.9, 0));

			drawInMode(GL_QUADS, points);

			points.clear();
		}

		// Draw main hand key.
		if (hasInInventory(InventoryItem_GateKey))
		{
			setColor(1.0f, 0.0f, 1.0f);
		}
		else
		{
			setColor(0.0f, 1.0f, 1.0f);
		}

		points.push_back(drawPoint(col - 0.1, row + 0.7, 0));
		points.push_back(drawPoint(col + 0.1, row + 0.7, 0));
		points.push_back(drawPoint(col + 0.1, row + 0.9, 0));
		points.push_back(drawPoint(col - 0.1, row + 0.9, 0));

		drawInMode(GL_QUADS, points);

		points.clear();
	}
}


void Player::projectileDestroyed(Projectile* projectile)
{
	if (!ownedProjectiles.empty())
	{
		ownedProjectiles.erase(std::find(ownedProjectiles.begin(), ownedProjectiles.end(), projectile));
	}
}


void Player::setIgnoreInput(bool ignoreInput)
{
	this->ignoreInput = ignoreInput;
}


void Player::spawnProjectile(char id, int xSpawn, int ySpawn, int hDirection, int vDirection)
{
	if (ownedProjectiles.size() < projectilesAllowed)
	{
		Projectile* projectile = static_cast<Projectile*>(Spawner::getInstance()->spawn(Spawner::ID_Projectile, xSpawn, ySpawn, hDirection, vDirection, this));
		if (projectile)
		{
			ownedProjectiles.push_back(projectile);
		}
	}
}
